/****************************************************************************
 *
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

/**
 *  @file
 *  @author Gus Grubba <gus@auterion.com>
 *  Original work: The OpenPilot Team, http://www.openpilot.org Copyright (C)
 * 2012.
 */

//#define DEBUG_GOOGLE_MAPS
#include "QGCMapEngine.h"


#include <QByteArray>
#include <QEventLoop>
#include <QNetworkReply>
#include <QRegExp>
#include <QString>
#include <QTimer>
#include "GaodeMapProvider.h"

const char* UrlFactory::kCopernicusElevationProviderKey = "Copernicus Elevation";
const char* UrlFactory::kCopernicusElevationProviderNotice = "© Airbus Defence and Space GmbH";

//-----------------------------------------------------------------------------
UrlFactory::UrlFactory() : _timeout(5 * 1000) {

    // Warning : in _providersTable, keys needs to follow this format :
    // "Provider Type"
    // 只保留高德地图提供商
    _providersTable["Gaode Road"] = new GaodeRoadMapProvider(this);

}

void UrlFactory::registerProvider(QString name, MapProvider* provider) {
    _providersTable[name] = provider;
}

//-----------------------------------------------------------------------------
UrlFactory::~UrlFactory() {}

QString UrlFactory::getImageFormat(int id, const QByteArray& image) {
    QString type = getTypeFromId(id);
    if (_providersTable.find(type) != _providersTable.end()) {
        return _providersTable[getTypeFromId(id)]->getImageFormat(image);
    } else {
        qDebug() << "getImageFormat : Map not registered :" << type;
        return "";
    }
}

//-----------------------------------------------------------------------------
QString UrlFactory::getImageFormat(const QString& type, const QByteArray& image) {
    if (_providersTable.find(type) != _providersTable.end()) {
        return _providersTable[type]->getImageFormat(image);
    } else {
        qDebug() << "getImageFormat : Map not registered :" << type;
        return "";
    }
}
QNetworkRequest UrlFactory::getTileURL(int id, int x, int y, int zoom,
                                       QNetworkAccessManager* networkManager) {

    QString type = getTypeFromId(id);
    if (_providersTable.find(type) != _providersTable.end()) {
        return _providersTable[type]->getTileURL(x, y, zoom, networkManager);
    }

    qDebug() << "getTileURL : map not registered :" << type;
    return QNetworkRequest(QUrl());
}

//-----------------------------------------------------------------------------
QNetworkRequest UrlFactory::getTileURL(const QString& type, int x, int y, int zoom,
                                       QNetworkAccessManager* networkManager) {
    if (_providersTable.find(type) != _providersTable.end()) {
        return _providersTable[type]->getTileURL(x, y, zoom, networkManager);
    }
    qDebug() << "getTileURL : map not registered :" << type;
    return QNetworkRequest(QUrl());
}

//-----------------------------------------------------------------------------
quint32 UrlFactory::averageSizeForType(const QString& type) {
    if (_providersTable.find(type) != _providersTable.end()) {
        return _providersTable[type]->getAverageSize();
    }
    qDebug() << "UrlFactory::averageSizeForType " << type
        << " Not registered";

    //    case AirmapElevation:
    //        return AVERAGE_AIRMAP_ELEV_SIZE;
    //    default:
    //        break;
    //    }
    return AVERAGE_TILE_SIZE;
}

QString UrlFactory::getTypeFromId(int id) {
    for (auto it = _providersTable.constBegin(); it != _providersTable.constEnd(); ++it) {
        if ((int)(qHash(it.key()) >> 1) == id) {
            return it.key();
        }
    }
    qDebug() << "getTypeFromId : id not found" << id;
    return "";
}

MapProvider* UrlFactory::getMapProviderFromId(int id)
{
    QString type = getTypeFromId(id);
    if (!type.isEmpty()) {
        if (_providersTable.find(type) != _providersTable.end()) {
            return _providersTable[type];
        }
    }
    return nullptr;
}

//-----------------------------------------------------------------------------
// Todo : qHash produce a uint bigger than max(int)
// There is still a low probability for this to
// generate similar hash for different types
int
UrlFactory::getIdFromType(const QString& type)
{
    return (int)(qHash(type)>>1);
}

//-----------------------------------------------------------------------------
int
UrlFactory::long2tileX(const QString& mapType, double lon, int z)
{
    return _providersTable[mapType]->long2tileX(lon, z);
}

//-----------------------------------------------------------------------------
int
UrlFactory::lat2tileY(const QString& mapType, double lat, int z)
{
    return _providersTable[mapType]->lat2tileY(lat, z);
}


//-----------------------------------------------------------------------------
QGCTileSet
UrlFactory::getTileCount(int zoom, double topleftLon, double topleftLat, double bottomRightLon, double bottomRightLat, const QString& mapType)
{
	return _providersTable[mapType]->getTileCount(zoom, topleftLon, topleftLat, bottomRightLon, bottomRightLat);
}

bool UrlFactory::isElevation(int mapId){
    return _providersTable[getTypeFromId(mapId)]->_isElevationProvider();
}
